home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 015 / setupoki.arc / SETUPOKI.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-09-17  |  32.8 KB  |  675 lines

  1. ;    SETUPOKI.ASM -- memory-resident printer setup utility
  2. ;
  3. ;    Assemble, link, and EXE2BIN to SETUPOKI.COM.  To use, just run
  4. ;    SETUPOKI, which will install itself in memory.  This should
  5. ;    be done only once (until the system is rebooted).  When invoked
  6. ;    by the Ctrl and Right Shift keys being pressed together, it
  7. ;    will display a menu of function keys and resulting actions.
  8. ;    Many other keys are now accepted also, as explained below.
  9. ;    Invalid keys will cause a beep from the computer speaker.
  10. ;
  11. ;    If you are planning to modify SETUP.COM (Programming-
  12. ;    /Utilities, Volume 5, Number 12, pp. 274-276) using DEBUG,
  13. ;    you should add 33h bytes (the length of the Ziff-Davis
  14. ;    copyright notice we inserted into Jeff Prosise's code) to
  15. ;    each of the offset addresses mentioned in the text.  Thus,
  16. ;    for example, the two default color-attribute bytes (4Fh,
  17. ;    white on red, and 70h, black on white) are actually at
  18. ;    offsets 013F and 0140, respectively, not at 010C and 010D.
  19. ;    The 33h additional affects all the offset addresses shown.
  20. ;    In addition, however, note that the two bytes used to modi-
  21. ;    fy the printer port selection are at offsets 0C77 and 0C84
  22. ;    (not a simple addition of 33h to the offsets printed).
  23. ;
  24. ;    This copy of SETUPOKI.ASM has been further modified as follows:
  25. ;    The above adjustments to the DEBUG offsets are no longer valid.
  26. ;    The End key in the numeric pad is now used to exit from SETUPOKI.
  27. ;    F9 resets top-of-form with 11 inch form length.  Shft-F9 now
  28. ;    resets top-of-form also, but omits the last byte of the control
  29. ;    sequence so that a non-standard value may be entered manually.
  30. ;    Ctrl-F1 to Ctrl-F4 are accepted to select printers LPT1 to LPT4.
  31. ;    Alt-F1 to Alt-F4 are accepted to swap printers LPT1 to LPT4 with
  32. ;    printer LPT1.  To avoid any confusion which might result from
  33. ;    repeated swaps, the original ports are reset before each swap.
  34. ;    (LPT4 is not normally valid, but might be supported by some
  35. ;    BIOS implementations, since there are 4 entries in the table.)
  36. ;    Valid ASCII characters (less than 128) are accepted and passed
  37. ;    to the printer for forms setup or whatever.  Some control keys
  38. ;    are very useful; for example, ^L (FF) will skip to top-of-form.
  39. ;    Return gives CR only; use ^J if you want a LineFeed (LF).
  40. ;
  41. interrupts    segment at 0h                      ;interrupt table segment
  42.               org 9h*4
  43. keyboard_int  dw 2 dup (?)                       ;interrupt 9 vector
  44. interrupts    ends
  45. ;
  46. rom_bios_data segment at 40h                     ;ROM BIOS data area segment
  47.               org 8h
  48. printer_base  dw 4 dup (?)                       ;line printer port addresses
  49. ;
  50.               org 60h
  51. cursor_mode   dw ?            ;starting and ending cursor scan lines
  52. rom_bios_data ends
  53. ;
  54. rom           segment at 0F000h                  ;ROM segment
  55.               org 0FFFEh
  56. ;
  57. machine_id    db ?                ;ID byte identifies machine as PCjr or other
  58. rom           ends
  59. ;
  60. code          segment para public 'code'         ;code segment
  61.               assume cs:code
  62.               org 100h
  63. ;
  64. begin:        jmp initialize                     ;goto initialization routine
  65. ;
  66.               db '(C) Copyright 1986, Ziff-Davis Publishing Company ', 1Ah
  67. ;
  68. column_count  dw ?                               ;width of window in columns
  69. cursor_type   dw ?                               ;cursor scan line definition
  70. setup_status  db 0          ;indicates if printer window is already active
  71. display_mode  dw ?                               ;current crt display mode
  72. page_no       dw ?                               ;current displayed page
  73. attribute1    db 4Fh                             ;window attribute bytes
  74. attribute2    db 70h
  75. ;
  76. display_table db 2Dh,29h    ;display re-enable values for modes 2 and 3
  77. video         dw 0B800h,0B900h,0BA00h,0BB00h     ;starting addresses of video
  78.                                                  ;memory for CGA pages 0 - 3
  79. ;
  80. mono_video    dw 0B000h                          ;video segment address for
  81.                          ;monochrome adapter
  82. ;
  83. printer_no    dw 0                               ;printer no. 0 - 3
  84. ;
  85. printer_save  dw 4 dup (?)                       ;save printer port addresses
  86. ;
  87. old_kb_int              label dword
  88. old_keyboard_int        dw 2 dup (?)             ;storage for old keyboard
  89.                          ;interrupt vector
  90. ;
  91. ;----------------------------------------------------------------------------
  92. ;Text of the Printer Setup Menu window.
  93. ;After initialization, text and attribute bytes are combined and stored
  94. ;in the WINDOW_TEXT area, and this area is used to store the contents of
  95. ;the screen that underlie the window when the window is called up.
  96. ;----------------------------------------------------------------------------
  97. ;
  98. window_buffer           label word
  99. buffer_text             db 201,26 dup (205),187
  100.                         db 186,'    SETUP PRINTER LPT1    ',186
  101.                         db 186,'   OKIDATA ',230,'92/93 - IBM   ',186
  102.                         db 199,26 dup (196),182
  103.                         db 186,' F1   Compressed Mode     ',186
  104.                         db 186,' F2   Expanded Mode       ',186
  105.                         db 186,' F3   Emphasized Mode     ',186
  106.                         db 186,' F4   Double-Strike Mode  ',186
  107.                         db 186,' F5   Correspondence Mode ',186
  108.                         db 186,' F6   Miniature Mode      ',186
  109.                         db 186,' F7   Skip Perforation    ',186
  110.                         db 186,' F8   8 Lines per Inch    ',186
  111.                         db 186,' F9   Reset Top-of-Form   ',186
  112.                         db 186,' F10  Reset Print Modes   ',186
  113.                         db 186,' END  Exit                ',186
  114.                         db 199,26 dup (196),182
  115.                         db 186,' Unshifted:   Toggle ON   ',186
  116.                         db 186,' Shifted:     Toggle OFF  ',186
  117.                         db 186,' Control:     Select LPTn ',186
  118.                         db 186,' Alternate:   Swap LPT1,n ',186
  119.                         db 200,26 dup (205),188
  120.                         db 588 dup (?)
  121. ;
  122. ;Storage area for the combination of text and attribute bytes that
  123. ;form the window image.
  124. ;
  125. window_bytes  label byte
  126. window_text   dw 588 dup (?)
  127. ;
  128. ;Control code strings for all of the printer setup options.
  129. ;
  130. code_table:   db 15,255,14 dup (0)            ;compressed mode on
  131.               db 27,87,1,255,12 dup (0)                 ;expanded mode on
  132.               db 27,69,255,13 dup (0)                   ;emphasized mode on
  133.               db 27,71,255,13 dup (0)                   ;double-strike mode on
  134.               db 27,88,1,255,12 dup (0)                 ;correspondence on
  135.               db 15,27,83,0,27,51,24,255,8 dup (0)      ;miniature mode on
  136.               db 27,78,12,255,12 dup (0)                ;perfskip on
  137.               db 27,48,255,13 dup (0)                   ;8 lines/inch
  138.               db 27,67,0,11,255,11 dup (0)              ;reset top-of-form
  139.               db 18,27,87,0,27,70,27,72,27,88,0,27,84,27,50,255      ;reset
  140.                                                                ;print modes
  141. ;
  142.               db 18,255,14 dup (0)                      ;compress off
  143.               db 27,87,0,255,12 dup (0)                 ;expand off
  144.               db 27,70,255,13 dup (0)                   ;emphasize off
  145.               db 27,72,255,13 dup (0)                   ;double-strike off
  146.               db 27,88,0,255,12 dup (0)                 ;correspondence off
  147.               db 18,27,84,27,50,255,10 dup (0)          ;miniature off
  148.               db 27,79,255,13 dup (0)                   ;perfskip off
  149.               db 27,50,255,13 dup (0)                   ;6 lines/inch
  150.               db 27,67,0,255,12 dup (0)                 ;reset top-of-form
  151.                                                         ;for manual length
  152. ;
  153. ;---------------------------------------------------------------------------
  154. ;Execution comes here, to the main body of the program, when an interrupt 9
  155. ;is generated from the keyboard.  Registers are saved, then the keypress is
  156. ;checked and compared to the key combination that activates the menu window.
  157. ;---------------------------------------------------------------------------
  158. ;
  159. main          proc near
  160.               sti                                ;enable software interrupts
  161.               push ax                            ;save all registers
  162.               push bx
  163.               push cx
  164.               push dx
  165.               push si
  166.               push di
  167.               push ds
  168.               push es
  169.               push ax                ;save ax for call to old routine
  170.               in al,0A0h                         ;re-enable NMI on PCjr
  171.               pop ax                             ;restore ax
  172.               pushf          ;simulate interrupt call to old keyboard routine
  173.               call old_kb_int                    ;call old routine
  174.               mov ah,2                   ;check status of the shift keys
  175.               int 16h
  176.               and al,5                           ;Ctrl and Rt-Shift depressed?
  177.               cmp al,5
  178.               je do_program                      ;yes, then skip exit routine
  179. ;
  180. ;Exit routine is the common point of exit for all routines in the program.
  181. ;
  182. exit:         pop es
  183.               pop ds
  184.               pop di
  185.               pop si
  186.               pop dx
  187.               pop cx
  188.               pop bx
  189.               pop ax
  190.               iret
  191. ;
  192. ;Execution comes here when the proper key combination, Ctrl/Rt-Shift, is
  193. ;pressed.  First task is to check whether or not the window is already open.
  194. ;
  195. do_program:   push cs              ;set es and ds to the code segment
  196.               pop ds
  197.               push cs
  198.               pop es
  199.               cmp setup_status,0                 ;is the window already open?
  200.               jne exit                           ;yes, then ignore request
  201. ;
  202. ;----------------------------------------------------------------------------
  203. ;Check current video mode.  If it's mode 2, 3, or 7, then set the window
  204. ;status flag, store the mode number and page number, save the cursor type,
  205. ;and hide the cursor.  If any other display mode is active instead, ignore
  206. ;the request and exit.
  207. ;----------------------------------------------------------------------------
  208. ;
  209.               mov ah,15                          ;get page and mode numbers
  210.               int 10h                            ;al=mode, bh=page
  211.               cmp al,2                ;is crt now in an acceptable mode?
  212.               je prog0                           ;yes, then continue
  213.               cmp al,3
  214.               je prog0
  215.               cmp al,7
  216.               je prog0
  217.               jmp exit                           ;no, then ignore request
  218. prog0:        mov setup_status,1                 ;set status flag to indicate
  219.                                                  ;that window is active
  220.               mov ah,0                           ;save mode number
  221.               mov display_mode,ax
  222.               push bx
  223.               mov bl,bh               ;save page number for color displays
  224.               mov bh,0
  225.               mov page_no,bx
  226.               pop bx
  227.               mov ah,3                           ;get cursor type
  228.               int 10h
  229.               mov cursor_type,cx                 ;save it
  230.               mov ah,1                           ;hide the cursor until later
  231.               mov ch,20h
  232.               int 10h
  233. ;
  234. ;Preparatory routines are completed.  Now open the window by first saving the
  235. ;contents of video memory beneath the window and then writing the window text
  236. ;directly to memory.
  237. ;
  238.               mov bx,page_no             ;use bx as index into video segment
  239.                                          ;address table
  240.               cmp display_mode,7         ;manually adjust index for monochrome
  241.                                          ;adapter
  242.               jne prog1
  243.               mov bx,4
  244. prog1:        shl bx,1                           ;multiply bx by two since
  245.                                                  ;table is made up of words
  246.               mov ax,video[bx]                   ;read segment from table
  247.               mov ds,ax                          ;ds set to video memory
  248.               cmp display_mode,7                 ;skip disable if in mode 7
  249.               je prog2
  250.               call video_disable      ;turn display off for snow-free writing
  251. prog2:        lea di,window_buffer         ;set di to buffer area to save
  252.                                            ;screen contents
  253.               mov ch,28               ;define window dimensions and location
  254.               mov cl,21
  255.               mov dh,2
  256.               mov dl,26
  257.               call video2mem          ;then transfer screen contents to buffer
  258.               push ds                            ;set es to video memory
  259.               pop es
  260.               push cs                            ;reset ds to code segment
  261.               pop ds
  262. ;
  263. prog3:        lea si,window_text                 ;point si to window image
  264.               mov ch,28                          ;define window region
  265.               mov cl,21
  266.               mov dh,2
  267.               mov dl,26
  268.               call mem2video         ;and write the window to the display
  269.               cmp display_mode,7                 ;skip enable if in mode 7
  270.               je getkey
  271.               call video_enable                  ;re-enable the video display
  272. ;
  273. ;Window is now present on the screen, so wait for a keypress.
  274. ;
  275. getkey:       mov ah,0                           ;get a keypress
  276.               int 16h
  277.               cmp al,0                           ;is it an extended code?
  278.               je extended_code                   ;yes, go interpret it
  279.               cmp al,127                         ;valid ASCII character?
  280.               ja getkey1                         ;no, illegal keypress
  281. ;
  282. ;A character has been entered which is to be passed thru to the printer.
  283. ;If the selected printer is powered off or off-line, beep instead.
  284. ;
  285.               call lptnstat                      ;check for printer ready
  286.               jc getkey1                         ;beep if printer not ready
  287.               mov dx,printer_no                  ;printer no. 0 - 3
  288.               mov ah,0
  289.               int 17h                            ;send byte to printer
  290.               jmp getkey                         ;return for another keypress
  291. ;
  292. ;An extended code has been entered...check its validity and goto the
  293. ;appropriate routine.
  294. ;
  295. extended_code:
  296.               cmp ah,59                          ;less than F1?
  297.               jb getkey1                         ;yes, reject it
  298.               cmp ah,68                          ;F1 thru F10?
  299.               jbe unshifted                      ;yes
  300.               cmp ah,79                          ;is it END key?
  301.               je endkey                          ;yes, restore and quit
  302.               cmp ah,84                          ;between F10 and Shft-F1?
  303.               jb getkey1                         ;yes, reject it
  304.               cmp ah,92                          ;Shft-F1 thru Shft-F9?
  305.               jbe shifted                        ;yes
  306.               cmp ah,94                          ;less than Ctrl-F1?
  307.               jb getkey1                         ;yes, reject it
  308.               cmp ah,97                          ;Ctrl-F1 thru Ctrl-F4?
  309.               jbe control                        ;yes
  310.               cmp ah,104                         ;less than Alt-F1?
  311.               jb getkey1                         ;yes, reject it
  312.               cmp ah,107                         ;Alt-F1 thru Alt-F4?
  313.               jbe alternate                      ;yes
  314. ;
  315. ;Getkey1 routine handles an illegal keypress by beeping and returning
  316. ;for another.
  317. ;
  318. getkey1:      call beep              ;beep and return for another keypress
  319.               jmp getkey
  320. ;
  321. ;----------------------------------------------------------------------------
  322. ;Execution comes here when the END key is pressed.  The window is refilled
  323. ;with its original contents, the cursor is restored, and control is handed
  324. ;back to the application program.
  325. ;----------------------------------------------------------------------------
  326. ;
  327. endkey:       cmp display_mode,7                 ;skip disable if in mode 7
  328.               je prog4
  329.               call video_disable                 ;turn off the display
  330. prog4:        lea si,window_buffer               ;point si to the buffer area
  331.               mov ch,28                          ;define the window
  332.               mov cl,21
  333.               mov dh,2
  334.               mov dl,26
  335.               call mem2video     ;and write the buffer contents to the display
  336.               cmp display_mode,7                 ;skip enable if in mode 7
  337.               je prog5
  338.               call video_enable                  ;turn display back on
  339. prog5:        mov ah,1                           ;restore cursor
  340.               mov cx,cursor_type
  341.               int 10h
  342.               mov setup_status,0                 ;reset window status
  343.               jmp exit                           ;and exit
  344. ;
  345. ;----------------------------------------------------------------------------
  346. ;If a legal function key was pressed, its scan code is translated here to the
  347. ;starting address of the string of bytes to be sent to the printer.  The
  348. ;string is then sent to LPTn: provided it's powered on and on-line.
  349. ;----------------------------------------------------------------------------
  350. ;
  351. shifted:      sub ah,15               ;adjustment for shifted function keys
  352. unshifted:    sub ah,59                ;adjustment for unshifted function keys
  353.               mov al,ah                          ;convert index to word in ax
  354.               xor ah,ah
  355.               mov cl,4                           ;multiply ax by 16
  356.               shl ax,cl
  357.               add ax,offset code_table     ;convert ax to full offset address
  358.               mov si,ax                          ;and transfer it to si
  359.               call lptnstat                      ;check for printer ready
  360.               jc getkey1                         ;beep if printer not ready
  361.               mov bl,255               ;specify delimiter for call to LPRINTZ
  362.               call lprintz             ;send control code string to printer
  363.               jmp getkey                         ;return for another keypress
  364. ;
  365. ;A key between Ctrl-F1 and Ctrl-F4 has been pressed.  The printer being
  366. ;setup is changed to LPTn where Ctrl-Fn is the key that was pressed.
  367. ;
  368. control:      sub ah,94                          ;make relative to 0
  369.               mov al,ah
  370.               mov ah,0
  371.               mov printer_no,ax                  ;save printer no. 0 - 3
  372.               inc al                             ;make relative to 1
  373.               or al,"0"                          ;change to ASCII digit
  374.               mov window_bytes+100,al            ;update window text
  375. ;
  376.               cmp display_mode,7                 ;skip disable if in mode 7
  377.               je jprog3
  378.               call video_disable      ;turn display off for snow-free writing
  379. jprog3:       jmp prog3                      ;go redisplay window
  380. ;
  381. ;A key between Alt-F1 and Alt-F4 has been pressed.  Printer LPT1 is
  382. ;swapped with printer LPTn where Alt-Fn is the key that was pressed.
  383. ;The printer ports are first reset to their original values.
  384. ;
  385. alternate:    sub ah,104                         ;make relative to 0
  386.               mov bl,ah
  387.               mov bh,0
  388.               shl bx,1                           ;double for word index
  389. ;
  390.               push es
  391.               mov ax,rom_bios_data               ;set es to ROM BIOS data area
  392.               mov es,ax
  393.               assume es:rom_bios_data
  394.               lea si,printer_save                ;point si to save area
  395.               lea di,printer_base                ;and di to printer_base
  396.               mov cx,4                           ;move 4 words
  397.               rep movsw
  398. ;
  399.               mov ax,printer_base                ;save LPT1 port
  400.               mov cx,printer_base[bx]            ;save LPTn port
  401.               mov printer_base[bx],ax            ;LPTn = saved LPT1
  402.               mov printer_base,cx                ;LPT1 = saved LPTn
  403.               pop es
  404.               assume es:nothing
  405.               jmp getkey                         ;return for another keypress
  406. ;
  407. main          endp                               ;end of main body of program
  408. ;
  409. ;---------------------------------------------------------------------------
  410. ;VIDEO_ENABLE and VIDEO_DISABLE routines manipulate bit 3 of port 3D8h,
  411. ;the CGA Mode Control Register, to temporarily turn the display on or off.
  412. ;Since these routines write directly to hardware, they have no effect on
  413. ;other video adapters.
  414. ;---------------------------------------------------------------------------
  415. ;
  416. video_disable proc near
  417.               mov dx,3DAh                        ;read CGA status port
  418. disable1:     in al,dx               ;wait for vertical retrace to occur
  419.               test al,8                          ;is bit 3 set?
  420.               je disable1                        ;no, wait until it is
  421.               mov dx,3D8h                        ;now disable the display
  422.               mov al,25h      ;by clearing bit 3 of the Mode Control Register
  423.               out dx,al
  424.               ret
  425. video_disable endp
  426. ;
  427. video_enable  proc near
  428.               mov dx,3D8h                        ;CGA Mode Control Register
  429.               mov bx,display_mode        ;get value to re-enable display
  430.               sub bx,2
  431.               mov al,display_table[bx]
  432.               out dx,al                          ;and send it to the port
  433.               ret
  434. video_enable  endp
  435. ;
  436. ;---------------------------------------------------------------------------
  437. ;VIDEO2MEM routine transfers the contents of a portion of video memory
  438. ;to a memory buffer for storage.
  439. ;Entry:       DS    - video segment
  440. ;             ES:DI - memory buffer
  441. ;             DH,DL - row and column of upper left corner of window
  442. ;             CH    - width of window in columns
  443. ;             CL    - number of lines in window
  444. ;---------------------------------------------------------------------------
  445. ;
  446. video2mem     proc near
  447.               mov al,ch                          ;store number of columns
  448.               mov ah,0
  449.               mov column_count,ax
  450.               mov ch,0                           ;cx = number of lines
  451.               push di                            ;save di
  452.               call video_offset        ;get cell address of first character
  453.               mov si,di                          ;put it in si
  454.               pop di                             ;restore di
  455. v2mem1:       push si                            ;save si for next line
  456.               push cx                            ;save line count
  457.               mov cx,column_count                ;set cx for call to WRITELN
  458.               call writeln                       ;transfer one line
  459.               pop cx                             ;restore saved registers
  460.               pop si
  461.               add si,160                         ;set si for next line address
  462.               loop v2mem1                ;loop until all lines are done
  463.               ret
  464. video2mem     endp
  465. ;
  466. ;---------------------------------------------------------------------------
  467. ;MEM2VIDEO writes a selected area of memory to the video display.
  468. ;Entry:       DS:SI - memory buffer
  469. ;             ES    - video segment
  470. ;             DH,DL - row and column of upper left corner of window
  471. ;             CH    - width of window in columns
  472. ;             CL    - number of lines in window
  473. ;---------------------------------------------------------------------------
  474. ;
  475. mem2video     proc near
  476.               mov al,ch                          ;save number of columns
  477.               mov ah,0
  478.               mov column_count,ax
  479.               mov ch,0                           ;cx = number of lines
  480.               call video_offset                  ;get offset into video memory
  481. mem2v1:       push di                            ;save video starting address
  482.               push cx                            ;save line count
  483.               mov cx,column_count                ;set cx for call to WRITELN
  484.               call writeln                       ;transfer one line
  485.               pop cx                             ;restore registers
  486.               pop di
  487.               add di,160                         ;set di for next display line
  488.               loop mem2v1                        ;loop until done
  489.               ret
  490. mem2video     endp
  491. ;
  492. ;---------------------------------------------------------------------------
  493. ;VIDEO_OFFSET calculates the offset into video memory of a character cell.
  494. ;Entry:       DH,DL - row and column of cell (0-24,0-79)
  495. ;Exit:        DI    - offset address
  496. ;---------------------------------------------------------------------------
  497. ;
  498. video_offset  proc near
  499.               mov al,160
  500.               mul dh                             ;row * 160
  501.               shl dl,1                           ;column * 2
  502.               mov dh,0                           ;byte to word
  503.               add ax,dx                          ;(row *160)+(column*2)
  504.               mov di,ax                          ;set offset in di
  505.               ret
  506. video_offset  endp
  507. ;
  508. ;---------------------------------------------------------------------------
  509. ;WRITELN subroutine copies a string of words from one memory location to
  510. ;another.  The CGA status port is not checked for vertical retrace status
  511. ;before transfer.
  512. ;Entry:       DS:SI - source
  513. ;             ES:DI - destination
  514. ;             CX    - number of words
  515. ;---------------------------------------------------------------------------
  516. ;
  517. writeln       proc near
  518.               cld                     ;clear for string instructions
  519. write1:       movsw                              ;move one word
  520.               loop write1                        ;loop until done
  521.               ret
  522. writeln       endp
  523. ;
  524. ;---------------------------------------------------------------------------
  525. ;LPRINTZ routine sends a string of bytes delimited by a user-specified byte
  526. ;to LPTn: thru INT 17h.
  527. ;Entry:       DS:SI - string address
  528. ;             BL    - delimiter (0-255)
  529. ;---------------------------------------------------------------------------
  530. ;
  531. lprintz       proc near
  532.               cld                                ;for 8088 string instructions
  533. lprintz1:     lodsb                              ;get one byte
  534.               cmp al,bl                          ;is it the delimiter?
  535.               je lprintz2                        ;yes, then exit
  536.               mov dx,printer_no                  ;printer no. 0 - 3
  537.               mov ah,0
  538.               int 17h                            ;send byte to printer
  539.               jmp lprintz1                       ;return for next byte
  540. lprintz2:     ret
  541. lprintz       endp
  542. ;
  543. ;---------------------------------------------------------------------------
  544. ;LPTNSTAT checks the current status of printer LPTn:.  If it's either
  545. ;powered off or off-line, then an error condition is signalled upon return
  546. ;thru the carry flag.
  547. ;Exit:        Carry clear - no error
  548. ;             Carry set   - error
  549. ;---------------------------------------------------------------------------
  550. ;
  551. lptnstat      proc near
  552.               mov dx,printer_no         ;printer no. 0 - 3
  553.               mov ah,2               ;use ROM BIOS 'get status' function
  554.               int 17h
  555.               test ah,8                 ;test bit 3, I/O error indicator
  556.               je stat1                  ;if clear, then no error
  557.               stc                       ;raise error flag
  558.               ret
  559. stat1:        clc                       ;clear error flag
  560.               ret
  561. lptnstat      endp
  562. ;
  563. ;---------------------------------------------------------------------------
  564. ;BEEP uses the 8253 timer chip to emit a short beep thru the PC's speaker.
  565. ;---------------------------------------------------------------------------
  566. ;
  567. beep          proc near
  568.               mov al,182             ;notify 8253 that frequency data is coming
  569.               out 67,al
  570.               mov al,0                           ;send frequency (776.8 Hz)
  571.               out 66,al
  572.               mov al,6
  573.               out 66,al
  574.               in al,97                           ;activate speaker
  575.               or al,3
  576.               out 97,al
  577.               mov cx,6000h                 ;time delay for sound duration
  578. beep1:        loop beep1
  579.               in al,97                           ;deactivate speaker
  580.               and al,252
  581.               out 97,al
  582.               ret
  583. beep          endp
  584. ;
  585. ;---------------------------------------------------------------------------
  586. ;Initialization routine sets up the window image in the WINDOW_TEXT area,
  587. ;resets the CURSOR_MODE word if this is a PCjr, and saves and replaces the
  588. ;old keyboard interrupt vector.
  589. ;---------------------------------------------------------------------------
  590. ;
  591. initialize    proc near
  592. ;
  593. ;Initialize the window text area by combining the text data with the attribute
  594. ;bytes and placing the conglomeration in the WINDOW_TEXT area.
  595. ;
  596.               assume ds:code,es:code
  597.               mov ah,15                          ;check the current video mode
  598.               int 10h
  599.               cmp al,7              ;if it's mode 7, then replace the attribute
  600.               jne init0          ;bytes with ones appropriate for mono adapter
  601.               mov attribute1,70h
  602.               mov attribute2,07h
  603. init0:        cld              ;now combine the text and attribute bytes
  604.               lea si,buffer_text                 ;point si to table of text
  605.               lea di,window_bytes                ;and di to storage area
  606.               mov cx,112           ;create first four lines by combining
  607.               mov al,attribute1          ;text with attribute1 (112 words)
  608. init1:        movsb                              ;text byte
  609.               stosb                              ;attribute byte
  610.               loop init1                 ;loop until all 112 words are done
  611.               mov cx,11                          ;now do the next 11 lines
  612. init2:        push cx              ;first attribute in each line is attribute1
  613.               movsb
  614.               stosb
  615.               mov cx,26            ;next 26 attributes are attribute2
  616.               mov al,attribute2
  617. init3:        movsb
  618.               stosb
  619.               loop init3
  620.               movsb
  621.               mov al,attribute1     ;and the last in each line is attribute1
  622.               stosb
  623.               pop cx
  624.               loop init2            ;loop until all 11 lines are done
  625.               mov cx,168            ;create the last six lines just like
  626. init4:        movsb                 ;the first four
  627.               stosb
  628.               loop init4
  629. ;
  630. ;Now save the printer_base table (port addresses) for printer swapping.
  631. ;
  632.               mov ax,rom_bios_data               ;set ds to ROM BIOS data area
  633.               mov ds,ax
  634.               assume ds:rom_bios_data
  635.               lea si,printer_base                ;point si to printer_base
  636.               lea di,printer_save                ;and di to save area
  637.               mov cx,4                           ;move 4 words
  638.               rep movsw
  639. ;
  640. ;Check the machine ID byte in ROM and if this is a PCjr, then reset the
  641. ;cursor and correct the CURSOR_MODE word at 0040:0060.
  642. ;
  643.               mov ax,rom                         ;set ds to rom
  644.               mov ds,ax
  645.               assume ds:rom
  646.               cmp machine_id,0FDh                ;is this a PCjr?
  647.               jne init5                          ;no, then skip this routine
  648.               mov ax,rom_bios_data               ;set ds to ROM BIOS data area
  649.               mov ds,ax
  650.               assume ds:rom_bios_data
  651.               mov cursor_mode,0607h          ;reset the cursor mode indicator
  652.               mov ah,1                       ;then physically reset the cursor
  653.               mov cx,0607h
  654.               int 10h
  655. ;
  656. ;Now save the old keyboard interrupt vector and replace it with the new one.
  657. ;
  658. init5:        mov ax,interrupts          ;set ds to the interrupt vector area
  659.               mov ds,ax
  660.               assume ds:interrupts
  661.               mov ax,keyboard_int                ;save old vector
  662.               mov old_keyboard_int,ax
  663.               mov ax,keyboard_int[2]
  664.               mov old_keyboard_int[2],ax
  665.               cli                        ;disable all interrupts but NMI
  666.               mov keyboard_int,offset main       ;and install new vector
  667.               mov keyboard_int[2],cs
  668.               sti                                ;re-enable interrupts
  669.               mov dx,offset initialize   ;point dx to end of resident section
  670.               int 27h                            ;terminate-but-stay-resident
  671. initialize    endp
  672. ;
  673. code          ends
  674.               end begin
  675.